package com.spring.theory.aop.jdkProxy;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import lombok.extern.slf4j.Slf4j;

/**
 * JdkProxyImprove
 * <p>
 * - jdk反射方法调用时，底层使用 MethodAccessor 类；sun.reflect.NativeMethodAccessorImpl可以看见这个次数优化
 * -- 在前16次使用 NativeMethodAccessorImpl 反射调用；在第17次使用 GenerateMethodAccessor2 生成一个代理类去调用(不使用反射)
 * 当达到阈值时，一个方法生成使用一个代理类，避免反射
 */
@Slf4j
public class JdkProxyImprove {

    public static void main(String[] args) throws Exception {
        Method method = JdkProxyImprove.class.getMethod("test", int.class);
        for (int i = 0; i < 20; i++) {
            show(i, method);
            method.invoke(null, i);
        }

    }

    private static void show(int i, Method foo) throws Exception {
        Method method = Method.class.getDeclaredMethod("getMethodAccessor");
        method.setAccessible(true);
        Object invoke = method.invoke(foo);
        if (invoke == null) {
            log.info(i + ":" + null);
            return;
        }
        // DelegatingMethodAccessorImpl 的全限定类名（不同版本的 JDK 存在差异）
        Field delegate = Class.forName("sun.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");
        delegate.setAccessible(true);
        log.info(i + ":" + delegate.get(invoke));
    }

    public static void test(int i) {
        log.info("test===>" + i);
    }

}
